import React, {Component} from 'react';
import MyHeader from "../MyUIComponent/MyHeader";
import {registerNode, Topology} from "@topology/core";
import {Tools} from "../config/config";
import {activityFinal, activityFinalIconRect, activityFinalTextRect} from "@topology/activity-diagram";
import {register as registerChart} from "@topology/chart-diagram/src/register";
import reactNodes from "../Layout/Plugin/React-nodes";
import {Button, DatePicker, Input, InputNumber, message, Modal, Table, Tabs} from "antd";
import {registerSelfMadeNode} from "../Components/registerSelfMadeNode";
import NodeComponent from "../Layout/component/nodeComponent";
import LineComponent from "../Layout/component/lineComponent";
import BackgroundComponent from "../Layout/component/backgroundComponent";
import {axiosPostFunction} from "../MyConfig/AppConfig";
import SystemComponent from "../Layout/LeftAreaComponent/SystemComponent";
import SelfMadeLogicComponentBox from "../MyUIComponent/LeftAreaComponentBox/SelfMadeLogicComponentBox";

const {TabPane} = Tabs;

class NewLogicWork extends Component {
    state = {
        // topology 需要进行配合的内容
        selected: {},
        isLoadCanvas: false,
        // 用户 id 信息
        user_id_str: "-1",
        // 控制保存 modal 显示的信息
        modal_visible: false,
        // 控制仿真的 modal 显示的信息
        modal_visible_run: false,
        // 为了处理多次保存的情况，在这里进行设置
        logic_work_id: -1,
        // 仿真步数
        step: 0,
        title: "",
        // 仿真运行结果
        result: [],
    }

    nodeFormRef = null

    dragRef = null

    canvas = null

    componentDidMount() {
        this.mainRegisterNode();
        this.canvas = new Topology('topology-canvas', {
            rotateCursor: '/rotate.cur',
            locked: 2,
            grid: true,
            ruleColor: '#2db7f5',
            on: this.onCanvasEvent
        });
        if (window.registerTools) {
            // 执行类的 constructor 方法
            window.registerTools();
            // Tools 是 src/config/config.js 文件里的一个 json 对象，是一个列表 [] 对象，其第 0 项是 react 组件
            // Tools[0] 的 children 当中，是 “React组件” 下的一些工具
            Tools[0].children = Tools[0].children.concat(
                window.topologyTools.map((el) => {
                    return {
                        data: el.data,
                        name: el.data.name,
                        icon: 'icon-anniu'
                    };
                })
            );
        }
        // canvas.open(example);
        let user_id = localStorage.getItem("userInfo:id");
        this.setState({
            isLoadCanvas: true,
            user_id_str: user_id,
        });
    }

    // 注册所有的可用组件
    mainRegisterNode = () => {
        // activity
        registerNode(
            'activityFinal',
            activityFinal,
            null,
            activityFinalIconRect,
            activityFinalTextRect
        );
        registerChart();
        // 注册系统自带的一些组件
        registerNode('button', reactNodes(Button), null, null, null);
        registerNode('datePicker', reactNodes(DatePicker), null, null, null);
        registerNode('table', reactNodes(Table), null, null, null);
        registerNode('input', reactNodes(Input), null, null, null);
        registerSelfMadeNode();
    }

    // canvas 事件处理 onMessage
    onCanvasEvent = (event, data) => {
        // console.log("src/Layout/index.js: onMessage: event: ", event);
        switch (event) {
            case 'node': // 节点
            case 'addNode':
                // 切换 node 的时候, 清空上一个节点残留的信息
                if (this.nodeFormRef && this.nodeFormRef.current) {
                    this.nodeFormRef.current.resetFields();
                }
                this.setState({
                    selected: {
                        node: data,
                        line: null,
                        multi: false,
                        nodes: null,
                        locked: data.locked
                    }
                })
                break;
            case 'line': // 连线
            case 'addLine':
                this.setState({
                    selected: {
                        node: null,
                        line: data,
                        multi: false,
                        nodes: null,
                        locked: data.locked
                    }
                })
                // 可见，这里的 data 就是那一条 “连线” 的信息，包含了 from 和 to
                break;
            case 'space': // 空白处
                this.setState({
                    selected: {
                        node: null,
                        line: null,
                        multi: false,
                        nodes: null,
                        locked: null
                    }
                })
                break;
            default:
                break;
        }
    };

    // 拖动开始事件
    onDrag = (event, node) => {
        // console.log('src/Layout/index.js: ondrag', node);
        event.dataTransfer.setData('Topology', JSON.stringify(node.data));
    };

    // 表格数据改变事件
    onHandleFormValueChange = (value) => {
        let { selected } = this.state;
        // 这里的 selected 是 state.selected 对象
        if (selected.node.name === 'echarts') {
            console.log("selected.node.name: echarts", selected.node);
            this.canvas.updateProps(selected.node);
            return;
        }
        // 如果是我自定义的组件，也按照上边的原则进行更新
        if (selected.node.isMyReactComponent !== null && selected.node.isMyReactComponent === true){
            console.log("selected.node.isMyReactComponent: selected.node: ",  selected.node,  value)
            // 后来发现好像不用这个也能够进行更新
            try {
                // this.canvas.updateProps(selected.node);
                this.canvas.updateProps(value);
            }catch (err){
                console.error(err);
            }
            // canvas.updateProps();
            return;
        }
        // 剩下的就是更新普通的组件内容了
        const {
            rotate,
            data,
            lineWidth,
            strokeStyle,
            dash,
            color,
            fontSize,
            fontFamily,
            fontColor,
            text,
            seriesFunction,
            ...other
        } = value;
        let changedValues = {
            node: {
                rect: other,
                fontColor,
                fontSize,
                fontFamily,
                rotate,
                lineWidth,
                strokeStyle,
                dash,
                text,
                data
            }
        };

        if (changedValues.node) {
            // 遍历查找修改的属性，赋值给原始 Node
            for (const key in changedValues.node) {
                if (Array.isArray(changedValues.node[key])) {
                } else if (typeof changedValues.node[key] === 'object') {
                    for (const k in changedValues.node[key]) {
                        selected.node[key][k] = changedValues.node[key][k];
                    }
                } else {
                    selected.node[key] = changedValues.node[key];
                }
            }
        }
        // canvas 是 Topology 的“画布”对象
        // canvas.updateProps() 方法用于更新画布
        // 这个方法的 API: updateProps(cache: boolean = true, pens?: Pen[])
        // console.log(selected.node);
        this.canvas.updateProps(selected.node);
    }

    // 当线条表单数据变化时, 重新渲染 canvas
    onHandleLineFormValueChange = (value) => {
        let { selected } = this.state;
        const {dash, lineWidth, strokeStyle, name, fromArrow, toArrow, ...other} = value;
        const changedValues = {
            line: {rect: other, lineWidth, dash, strokeStyle, name, fromArrow, toArrow}
        };
        if (changedValues.line) {
            // 遍历查找修改的属性，赋值给原始line
            for (const key in changedValues.line) {
                if (Array.isArray(changedValues.line[key])) {
                } else if (typeof changedValues.line[key] === 'object') {
                    for (const k in changedValues.line[key]) {
                        selected.line[key][k] = changedValues.line[key][k];
                    }
                } else {
                    selected.line[key] = changedValues.line[key];
                }
            }
        }
        this.canvas.updateProps(selected.line);
    }

    // 画布右侧配置区域
    rightAreaConfig = () => {
        let {selected} = this.state;
        return {
            // 对于 reactComponent 类型的组件的配置页
            node: selected && (
                <NodeComponent
                    data={selected}
                    onFormValueChange={this.onHandleFormValueChange}
                    // onEventValueChange={onEventValueChange}
                    // onUpdateComponentProps={(value) => onUpdateComponentProps(value)}
                    // onUpdateHttpProps={(value) => onUpdateHttpProps(value)}
                    ref={this.nodeFormRef}
                />
            ), // 渲染 Node 节点类型的组件
            line: selected && (
                <LineComponent data={selected} onFormValueChange={this.onHandleLineFormValueChange}/>
            ), // 渲染线条类型的组件
            default: this.canvas && <BackgroundComponent data={this.canvas}/> // 渲染画布背景的组件
        };
    }

    // 染画布右侧区域操作栏，是直接 render 的这里的内容
    renderRightArea = (selected) => {
        // let { selected } = this.state;
        let rightAreaConfig = this.rightAreaConfig();
        let _component = rightAreaConfig.default;
        console.log("rightAreaConfig: selected: ", selected);
        if (selected && selected.node){
            _component = rightAreaConfig.node;
        }else if (selected && selected.line) {
            _component = rightAreaConfig.line;
        }
        return _component;
    }

    // “运行弹出框”当中的"确认保存"按钮之后的事件
    onClickSave = () => {
        let {
            user_id_str,
            logic_work_id,
            step,
            title,
        } = this.state;
        // console.log(this.canvas, this.canvas.data)
        let url = "/logic_work/update";
        if (logic_work_id < 0){
            url = "/logic_work/new"
        }
        axiosPostFunction(url, {
            author_id: parseInt(user_id_str, 10),
            logic_work_id,
            step,
            title,
            content: JSON.stringify(this.canvas.data),
        }, (received_data)=>{
            console.log("received_data: ", received_data)
            let { logic_work_id } = received_data;
            this.setState({
                logic_work_id,
                modal_visible: false,
            }, ()=>{
                message.success("保存成功！")
            })
        }, ()=>{
            message.error("保存失败！")
        })
    }

    // “仿真弹出框”当中的“确认运行”按钮之后的事件
    onClickRun = () => {
        let {
            user_id_str,
            logic_work_id,
            step,
        } = this.state;
        // console.log(this.canvas, this.canvas.data)
        axiosPostFunction("/function/run", {
            author_id: parseInt(user_id_str, 10),
            logic_work_id,
            step,
            content: JSON.stringify(this.canvas.data),
        }, (received_data)=>{
            console.log("received_data: ", received_data)
            let { dataList } = received_data;
            this.setState({
                result: dataList,
                modal_visible_run: false,
            }, ()=>{
                message.success("运行成功！")
            })
        }, ()=>{
            message.error("运行失败！")
        })
    }

    // 渲染函数
    render() {
        let {selected, modal_visible, modal_visible_run, step, title} = this.state;
        return (
            <div>
                <MyHeader
                    pathname="new_logic_work"
                    onClickSave={()=>{ this.setState({ modal_visible: true }) }}
                    onClickRun={()=>{ this.setState({ modal_visible_run: true }) }}
                />
                <div className="page">
                    {/* 左侧组件箱 */}
                    <div className="tool">
                        <Tabs defaultActiveKey="1">
                            <TabPane tab="系统组件" key="1" style={{margin: 0}}>
                                <SystemComponent onDrag={this.onDrag} allowDrop={this.allowDrop} Tools={Tools}/>
                            </TabPane>
                            <TabPane tab="我的组件" key="2" style={{margin: 0}}>
                                <SelfMadeLogicComponentBox/>
                                {/*<MyComponent/>*/}
                            </TabPane>
                        </Tabs>
                    </div>
                    {/* 中间画布 */}
                    <div className="full" style={{ overflow: "hidden" }}>
                        <div style={{minWidth: 1200}}>
                            {/* 下面是渲染画布 */}
                            <div
                                id="topology-canvas"
                                style={{
                                    width: 1200,
                                    height: 800,
                                    boxShadow: '2px 0 10px rgb(0 0 0 / 20%)',
                                    position: 'relative',
                                    margin: '0px 0px',
                                }}
                            >
                                <div
                                    ref={this.dragRef}
                                    style={{
                                        position: 'absolute',
                                        right: 0,
                                        bottom: 0,
                                        width: 10,
                                        height: 10,
                                        zIndex: 999,
                                        background: 'gray',
                                        cursor: 'cell'
                                    }}
                                />
                            </div>
                        </div>
                    </div>
                    {/* 右侧属性显示和编辑模块 */}
                    <div className="props">
                        {(selected && selected.node) && this.renderRightArea(selected)}
                    </div>
                </div>
                <Modal
                    visible={modal_visible}
                    title="保存配置"
                    onCancel={()=>{ this.setState({ modal_visible: false })}}
                    onOk={this.onClickSave}
                >
                    <Input
                        onChange={(event)=>{
                            this.setState({ title: event.target.value })
                        }}
                        placeholder="仿真标题"
                        value={ title }
                        style={{ margin: "10px 0" }}
                    />
                </Modal>
                <Modal
                    visible={modal_visible_run}
                    title="仿真配置"
                    onCancel={()=>{ this.setState({ modal_visible_run: false })}}
                    onOk={this.onClickRun}
                >
                    <h3>设置仿真步长</h3>
                    <InputNumber
                        onChange={(input_number)=>{ this.setState( {step: input_number} ) }}
                        placeholder="仿真步数"
                        value={step}
                        min={0}
                        max={999}
                        style={{ margin: "10px 0" }}
                    />
                </Modal>
            </div>
        );
    }
}

export default NewLogicWork;
